package com.zengchen.user.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zengchen.common.bean.ResponseVO;
import com.zengchen.common.enums.ResponseCode;
import com.zengchen.common.utils.JWTUtils;
import com.zengchen.common.utils.OkhttpUtil;
import com.zengchen.content.common.PoemOT;
import com.zengchen.user.common.PointLogType;
import com.zengchen.user.common.UserInfoOT;
import com.zengchen.user.config.JwtConfig;
import com.zengchen.user.config.WXConfig;
import com.zengchen.user.entity.CurrentPoem;
import com.zengchen.user.entity.Member;
import com.zengchen.user.entity.PointLog;
import com.zengchen.user.feignclient.ContentCenterFeignClient;
import com.zengchen.user.service.CurrentPoemService;
import com.zengchen.user.service.MemberService;
import com.zengchen.user.service.PointLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author zengchen123
 * @since 2019-09-04
 */
@RestController
@Slf4j
public class LoginController {

    @Autowired
    private WXConfig wxConfig;

    @Autowired
    private JwtConfig jwtConfig;

    @Autowired
    private MemberService memberService;

    @Autowired
    private PointLogService pointLogService;

    @Autowired
    private CurrentPoemService currentPoemService;


    @Autowired
    private ContentCenterFeignClient contentCenterFeignClient;

    @PostMapping("login")
    public Object login(@RequestBody String requestBody) {
        Map<String,Object> responseData = new HashMap<>();
        try {
            log.info("login start with requestBody={}", requestBody);
            // 1,获取请求参数
            JSONObject requestOjt = JSON.parseObject(requestBody);
            String tempCode = requestOjt.getString("code");
            JSONObject userInfo = requestOjt.getJSONObject("userInfo");

            // 2,检查请求参数
            if (StringUtils.isBlank(tempCode) || StringUtils.isBlank(userInfo.getString("gender"))) {
                return ResponseVO.fail(ResponseCode.ERROR_PARAMS);
            }

            // 3.调用auth.code2Session，获取openid
            String targetUrl = wxConfig.getCode2Session_url().replace("APPID", wxConfig.getAppid())
                    .replace("SECRET", wxConfig.getSecret()).replace("JSCODE", tempCode);
            log.info("auth.code2Session targetUrl = {}", targetUrl);
            String response = OkhttpUtil.get(targetUrl,null,null);
            log.info("auth.code2Session response = {}", response);
            JSONObject responseOjt = JSON.parseObject(response);
            String openid = responseOjt.getString("openid");
            if (StringUtils.isBlank(openid)) {
                String errMsg = responseOjt.getString("errmsg");
                return ResponseVO.fail(ResponseCode.ERROR_LOGIN.getCode(), errMsg);
            }

            // 4.检查用户是否已经注册，未注册的先注册
            log.info("检查是否注册，openid = {}",openid);
            Member member = memberService.getOne(new QueryWrapper<Member>().eq("wx_id", openid));
            if(null == member){
                log.info("用户未注册");
                // 1.注册
                log.info("注册");
                member = new Member();
                member.setWxId(openid);
                member.setSex(userInfo.getString("gender"));
                member.setHeadUrl(userInfo.getString("avatarUrl"));
                member.setNickname(userInfo.getString("nickName"));
                member.setCreateTime(LocalDateTime.now());
                member.setUpdateTime(member.getCreateTime());
                member.setPoints(PointLogType.REGISTER.getAmount());
                memberService.save(member);

                log.info("发放注册积分");
                // 2.发放注册积分
                // TODO 使用消息队列 做成异步的
                PointLog pointLog = new PointLog();
                pointLog.setMemberId(member.getId());
                pointLog.setAmount(PointLogType.REGISTER.getAmount());
                pointLog.setType(PointLogType.REGISTER.getType());
                pointLog.setRemarks(PointLogType.REGISTER.getRemarks());
                pointLog.setCreateTime(new Date());
                pointLogService.save(pointLog);

                // 3.发放第一首诗词
                log.info("发放第一首诗词");
                CurrentPoem currentPoem = new CurrentPoem();
                currentPoem.setMemberId(member.getId());
                currentPoem.setStayDays(0);
                currentPoem.setHappenedDate(LocalDateTime.now());
                currentPoem.setStatus("N");
                currentPoem.setUpdateDate(LocalDate.now());
//                PoemOT firstPoem = contentCenterFeignClient.getPoemByOrder(1);
                // 随机发放一首诗词
                List<PoemOT> allPoem = contentCenterFeignClient.getAllPoem();
                PoemOT poemOT = allPoem.get(ThreadLocalRandom.current().nextInt(allPoem.size()));
                currentPoem.setPoemId(poemOT.getId());
                currentPoemService.save(currentPoem);
            }
            Integer memberId = member.getId();
            // 5.发放 Token
            Map<String,Object> claims = new HashMap<>();
            claims.put("memberId",memberId);
            claims.put("nickName",member.getNickname());
            claims.put("headUrl",member.getHeadUrl());
            String token = JWTUtils.generateToken(claims,jwtConfig.getSecret(),Long.valueOf(jwtConfig.getExpirationTimeInSecond()));
            log.info("发放 token = {}",token);

            log.info("获取my页面的数据");
            UserInfoOT userInfoOT = memberService.getMyPageUserInfoOT(member);
            userInfoOT.setToken(token);

            responseData.put("userInfoOT",userInfoOT);
            log.info("login end with success");
            return ResponseVO.success(responseData);
        } catch (Exception e) {
            log.error("login end with exception", e);
            return ResponseVO.fail(ResponseCode.ERROR_LOGIN);
        }
    }

}

